/***************************************************************************
 *                                                                         *
 * Copyright (c) 2007 - 2009 Nuvoton Technology Corp. All rights reserved.*
 *                                                                         *
 ***************************************************************************/
 
/****************************************************************************
 * 
 * FILENAME
 *     NUC900_VPOST_Driver.c
 *
 * VERSION
 *     0.1 
 *
 * DESCRIPTION
 *
 *
 *
 *
 * DATA STRUCTURES
 *     None
 *
 * FUNCTIONS
 *
 *
 *     
 * HISTORY
 *     2005.03.16		Created by Shih-Jen Lu
 *
 *
 * REMARK
 *     None
 *
 *
 **************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "wblib.h"
#include "NUC900_VPOST_Regs.h"
#include "NUC900_VPOST.h"

UINT g_nFrameBufferSize = 0;

VOID vpostVAStartTrigger()
{
    if((inpw(REG_LCM_DCCS) & VPOSTB_SINGLE) == VPOSTB_SINGLE)
    	while((inpw(REG_LCM_DCCS) & VPOSTB_VA_EN) == VPOSTB_VA_EN);//wait VA_EN low
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | VPOSTB_DISP_OUT_EN); //display_out-enable
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | VPOSTB_VA_EN); //va-enable
}

VOID vpostVAStopTrigger()
{
     outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~(VPOSTB_DISP_OUT_EN | VPOSTB_VA_EN));//OSD disable
     
}

VOID vpostVAScalingCtrl(UINT8 ucHIntegral,UINT16 usHDecimal,UINT8 ucVIntegral,UINT16 usVDecimal,UINT8 ucmode)
{
	outpw(REG_LCM_VA_SCALE,((((UINT32)ucVIntegral << 10) + ((UINT32)ceil((double)1024/10)*usVDecimal)) << 16)
							| (((UINT32)ucHIntegral << 10) + ((UINT32)ceil((double)1024/10)*usHDecimal)) | ucmode);
}
/* For align 32 */
static UINT32 shift_pointer(UINT32 ptr, UINT32 align)   
{
	UINT32 alignedPTR;
	UINT32 remain;
	
	//printf("pointer position is %x\n",ptr);
	if( (ptr%align)!=0)
	{
		remain = ptr % align;
		alignedPTR = ptr + (align - remain);
		return alignedPTR;
	}
	return ptr;
}
BOOL vpostAllocVABuffer(PLCDFORMATEX plcdformatex,UINT32 nBytesPixel)
{
	g_nFrameBufferSize = plcdformatex->nFrameBufferSize+32;
    g_VAOrigFrameBuf = (PUINT32)malloc(plcdformatex->nFrameBufferSize+32);
	g_VAFrameBuf = (VOID*)shift_pointer((UINT32)g_VAOrigFrameBuf,32);
	//g_VAFrameBuf = (PUINT32)0x1000000;  // for testing
	if (g_VAFrameBuf == NULL)
		return FALSE;
    
    //if (sysCacheState())//set uncache buffer for CPU
    if (sysGetCacheState())//set uncache buffer for CPU
    {
        g_VAFrameBuf = (VOID*)((UINT32)g_VAFrameBuf | 0x80000000);
    }

    memset(g_VAFrameBuf,0,g_nFrameBufferSize);
    
    outpw(REG_LCM_VA_BADDR0,(UINT32)g_VAFrameBuf);
    outpw(REG_LCM_VA_FBCTRL,inpw(REG_LCM_VA_FBCTRL) & ~(1<<30) & ~VPOSTB_DB_EN);//fetch data from VA_BADDR0    
    
	return TRUE;
}
BOOL vpostClearVABuffer()
{
	if (g_VAOrigFrameBuf != NULL)
    {
        memset(g_VAOrigFrameBuf,0,g_nFrameBufferSize);
        return TRUE;
    }    
    else
        return FALSE;
}

BOOL vpostFreeVABuffer()
{
    if (g_VAOrigFrameBuf != NULL)
    {
        free(g_VAOrigFrameBuf);
        return TRUE;
    }    
    else
        return FALSE;
}

VOID vpostSetOSDSrc(UINT16 ucOSDSrcType)
{
	
	writew(REG_LCM_DCCS,readw(REG_LCM_DCCS) &~(7<<12) | ucOSDSrcType);
}

VOID vpostSetVASrc(UINT16 ucVASrcType)
{
	outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~(7<<8));
	if (ucVASrcType != 0)
		outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | ucVASrcType);
	else
		outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~(7<<8));
}

VOID vpostSetDisplayMode(UINT8 ucvdismode)
{
	if (ucvdismode==0)
		outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~(1<<7));//clear setting
	else		
    	outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | ucvdismode);
}

INT vpostSetOSDBuffer(PUINT32 pFrameBuffer)
{
	if (pFrameBuffer==NULL){
		return ERR_NULL_BUF; 
	}
	writew(REG_LCM_OSD_BADDR,(UINT32)pFrameBuffer);
	return 0;
}
VOID vpostOSDEnable(VOID)
{
     outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | VPOSTB_OSD_EN);//OSD enable
}
VOID vpostOSDScalingCtrl(UINT8 ucHIntegral,UINT16 usHDecimal,UINT8 ucVScall)
{
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS)&0xfff0ffff);//clear OSD scalling setting
    if (ucVScall!=0)
    	outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | (ucVScall<<16));
    //if (ucHScall!=0)
    //	outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | (ucHScall<<18));
    outpw(REG_LCM_OSD_SCALE, ((UINT32)ucHIntegral<<10) | ((UINT32)ceil((double)1024/10*usHDecimal))<<6);
    
}
VOID vpostLCDWriteAddr(UINT16 uscmd)
{
    outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) & ~VPOSTB_WR_RS);         //RS=0
    outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) & ~VPOSTB_READ);         //w
    outpw(REG_LCM_DCCS,(inpw(REG_LCM_DCCS) | VPOSTB_CMD_ON));       //CMD ON
    
    outpw(REG_LCM_MPU_CMD,(inpw(REG_LCM_MPU_CMD) & 0xffff0000 | uscmd));
    while(inpw(REG_LCM_MPU_CMD)&VPOSTB_CMD_BUSY); //CNLi
    
    outpw(REG_LCM_DCCS,(inpw(REG_LCM_DCCS)&~VPOSTB_CMD_ON));         //CMD OFF
}
VOID vpostLCDWriteAddr9BIT(UINT16 uscmd)
{
	outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) & ~VPOSTB_WR_RS);         //RS=0
    outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) & ~VPOSTB_READ);         //w
    outpw(REG_LCM_DCCS,(inpw(REG_LCM_DCCS) | VPOSTB_CMD_ON));       //CMD ON
    outpw(REG_LCM_MPU_CMD,((inpw(REG_LCM_MPU_CMD)&0xffff0000)|(UINT8)(uscmd>>8)));
    while(inpw(REG_LCM_MPU_CMD) & VPOSTB_CMD_BUSY); //CNLi
    outpw(REG_LCM_MPU_CMD,((inpw(REG_LCM_MPU_CMD)&0xffff0000)|(UINT8)(uscmd&0x00ff)));
    while(inpw(REG_LCM_MPU_CMD) & VPOSTB_CMD_BUSY); //CNLi
    outpw(REG_LCM_DCCS,(inpw(REG_LCM_DCCS)& ~VPOSTB_CMD_ON));         //CMD OFF
}

VOID vpostLCDWriteData(UINT16 usdata)
{
    outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) | VPOSTB_WR_RS);         //RS=1
    outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) & ~VPOSTB_READ);         //w
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | VPOSTB_CMD_ON);       //CMD ON
    outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) & 0xffff0000 |usdata);
    while(inpw(REG_LCM_MPU_CMD) & VPOSTB_CMD_BUSY); //CNLi
	outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~VPOSTB_CMD_ON);         //CMD OFF
}

VOID vpostLCDWriteData9BIT(UINT16 usdata)
{
	outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) | VPOSTB_WR_RS);         //RS=1
    outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) & ~VPOSTB_READ);         //w
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | VPOSTB_CMD_ON);       //CMD ON
    outpw(REG_LCM_MPU_CMD,((inpw(REG_LCM_MPU_CMD)&0xffff0000)|(UINT8)(usdata>>8)));
    while(inpw(REG_LCM_MPU_CMD) & VPOSTB_CMD_BUSY); //CNLi
    outpw(REG_LCM_MPU_CMD,((inpw(REG_LCM_MPU_CMD)&0xffff0000)|(UINT8)(usdata&0x00ff)));
    while(inpw(REG_LCM_MPU_CMD) & VPOSTB_CMD_BUSY); //CNLi
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~VPOSTB_CMD_ON);         //CMD OFF
}

UINT32 vpostLCDReadData()
{
    UINT32 udata;
    outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) | VPOSTB_WR_RS);         //RS=1
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | VPOSTB_CMD_ON);       //CMD ON
    outpw(REG_LCM_MPU_CMD,inpw(REG_LCM_MPU_CMD) | VPOSTB_READ);         //r
    while(inpw(REG_LCM_MPU_CMD) & VPOSTB_CMD_BUSY); //CNLi
    udata = inpw(REG_LCM_MPU_CMD) & 0xffff;
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~VPOSTB_CMD_ON);         //CMD OFF
    return udata;
}

VOID vpostOSDSetWindow(UINT32 usxstart,UINT32 usystart,UINT32 uwidth,UINT32 uheight)
{
    writew(REG_LCM_OSD_WINS,((usystart+1)<<16) | (usxstart+1));
    writew(REG_LCM_OSD_WINE,((usystart+uheight)<<16) | (usxstart+uwidth));
}

#if 0
UINT8 vpostCheck_CRC(UINT16 usSR,UINT16 usSG,UINT16 usSB)
{
    UINT16 sigR, sigG, sigB;

    vpostOSD_Disable();
    vpostVA_Disable();
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS)|0x00000080); //rgb565,single
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS)|0x00000008); //display_out-enable
/*--- R ---*/
    outpw(REG_LCM_VA_TEST,0x00000002);//r
    outpw(REG_LCM_VA_TEST,0x0000000a);
    outpw(REG_LCM_VA_TEST,0x0000000b);
    while((inpw(REG_LCM_VA_TEST) & 0x00000080)==0x00000000);	// wait	for CRC	ready
    outpw(REG_LCM_VA_TEST,0x0000000a);
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS)|0x00000002); //va-enable
//    while((inpw(REG_LCM_DCCS) & 0x10000000)!=0x00000000);// wait for vertical retrace
    while((inpw(REG_LCM_VA_TEST) & 0x00000080)==0x00000080);	// wait	for CRC	ready
    while((inpw(REG_LCM_DCCS)&0x00000002)==0x00000002);
    sigR = (UINT16)(inpw(REG_LCM_VA_TEST)>>16);

/*--- G ---*/
    outpw(REG_LCM_VA_TEST,0x00000004);
    outpw(REG_LCM_VA_TEST,0x0000000c);
    outpw(REG_LCM_VA_TEST,0x0000000d);
    while((inpw(REG_LCM_VA_TEST) & 0x00000080)==0x00000000);	// wait	for CRC	ready
    outpw(REG_LCM_VA_TEST,0x0000000c);
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS)|0x00000002); //va-enable
//    while((inpw(REG_LCM_DCCS) & 0x10000000)!=0x00000000);// wait for vertical retrace
    while((inpw(REG_LCM_VA_TEST) & 0x00000080)==0x00000080);	// wait	for CRC	ready
    while((inpw(REG_LCM_DCCS)&0x00000002)==0x00000002);
    sigG = (UINT16)(inpw(REG_LCM_VA_TEST)>>16);

/*--- B ---*/
    outpw(REG_LCM_VA_TEST,0x00000006);
    outpw(REG_LCM_VA_TEST,0x0000000e);
    outpw(REG_LCM_VA_TEST,0x0000000f);
    while((inpw(REG_LCM_VA_TEST) & 0x00000080)==0x00000000);	// wait	for CRC	ready
    outpw(REG_LCM_VA_TEST,0x0000000e);
    outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS)|0x00000002); //va-enable
//    while((inpw(REG_LCM_DCCS) & 0x10000000)!=0x00000000);// wait for vertical retrace
    while((inpw(REG_LCM_VA_TEST) & 0x00000080)==0x00000080);	// wait	for CRC	ready
    while((inpw(REG_LCM_DCCS)&0x00000002)==0x00000002);
    sigB = (UINT16)(inpw(REG_LCM_VA_TEST)>>16);

    if ((sigR==usSR)&&(sigG==usSG)&&(sigB==usSB))
       return 0;
    else
       return 1;
}
#endif